package com.bupt.kgplatform.service.impl;

import com.bupt.kgplatform.Util.R;
import com.bupt.kgplatform.mapper.DataCleanTaskMapper;
import com.bupt.kgplatform.service.DockerService;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.api.model.Bind;
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.PortBinding;
import com.github.dockerjava.api.model.Volume;
import com.github.dockerjava.core.DockerClientBuilder;
import com.jcraft.jsch.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;

/**
 * DockerServiceImpl
 *
 * @author zrz
 * @date 2023/5/26
 * @time 13:32
 * @Description dockerimpl
 */
@Service
public class DockerServiceImpl implements DockerService {

    @Value("${docker.address}")
    public String host;



    /**
     *
     * @author zrz
     * @date 2023/5/26
     * @time 13:35
     * @Description 创建容器
     */


    @Override
    public R createContainers(String containerName, int port) {
        String publicPort = String.valueOf(port);
        DockerClient dockerClient = DockerClientBuilder.getInstance(host).build();
        String imageName = "jupyter/datascience-notebook";
        String workingDir = "/home/jovyan/work";
        String mountPath = "/root/Project/jupyter-docker/data1";
        long memoryLimit = 1024 * 1024 * 1024; // 1024MB


        // 创建容器
        PortBinding portBinding = PortBinding.parse( publicPort + ":" + "8888");

        Bind bind = new Bind(mountPath, new Volume(workingDir));
        HostConfig hostConfig = HostConfig.newHostConfig().
                withPortBindings(portBinding).  // 进行端口暴露映射
                        withBinds(bind).                // 进行目录挂载映射
                        withMemory(memoryLimit);

        CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
                .withName(containerName)      // 设置容器名称
                .withHostConfig(hostConfig)
                .withWorkingDir(workingDir)   // 设置容器内的工作目录
                .withCmd("start-notebook.sh", "--NotebookApp.token=\"cad\"", "--NotebookApp.password=\"\"")
                .exec();

        // 启动容器
        dockerClient.startContainerCmd(container.getId()).exec();

        // 检查容器状态
        InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(container.getId()).exec();

        // 获取容器状态
        InspectContainerResponse.ContainerState containerState = containerInfo.getState();

        if (Boolean.TRUE.equals(containerState.getRunning())) {
            System.out.println("容器创建成功！");
            return R.ok("容器创建成功！");
        } else {
            System.out.println("容器创建失败！");
            return R.failure(containerInfo);
        }


    }

    /**
     *
     * @author zrz
     * @date 2023/5/26
     * @time 17:19
     * @Description  检查容器是否还在运行，没找到该容器的话返回0，正在运行的话返回1，不在运行的话返回2
     */
    @Override
    public int checkContainer(String containerName){
        DockerClient dockerClient = DockerClientBuilder.getInstance(host).build();
        try {
            InspectContainerResponse inspectContainerResponse = dockerClient.inspectContainerCmd(containerName).exec();

            String status = inspectContainerResponse.getState().getStatus();

            if (status.equals("exited")) {
                System.out.println("Container " + containerName + " has stopped.");
                return 2;
            } else {
                System.out.println("Container " + containerName + " is still running.");
                return 1;
            }
        } catch (NotFoundException ex) {
            System.err.println("Container " + containerName + " not found.");
            return 0;
        }
    }

    /**
     *
     * @author zrz
     * @date 2023/5/26
     * @time 17:29
     * @Description  停止运行指定镜像
     */
    @Override
    public R stopContainer(String containerName){
        DockerClient dockerClient = DockerClientBuilder.getInstance(host).build();
        try {
            StopContainerCmd stopContainerCmd = dockerClient.stopContainerCmd(containerName);
            stopContainerCmd.exec();
            System.out.println("Container " + containerName + " stopped successfully.");
            return R.ok("Container " + containerName + " stopped successfully.");
        } catch (NotFoundException ex) {
            System.err.println("Container " + containerName + " not found.");
            return R.failure("Container " + containerName + " not found.");
        }
    }

    /**
     *
     * @author zrz
     * @date 2023/5/26
     * @time 17:29
     * @Description  重启指定镜像
     */
    @Override
    public R restartContainer(String containerName){
        int result =  checkContainer(containerName);
        if(result == 2){
            DockerClient dockerClient = DockerClientBuilder.getInstance(host).build();
            RestartContainerCmd restartContainerCmd = dockerClient.restartContainerCmd(containerName);
            restartContainerCmd.exec();
            System.out.println("Container " + containerName + " restarted successfully.");
            return R.ok("Container " + containerName + " restarted successfully.");
        } else if (result == 1) {
            System.out.println("Container " + containerName + " is still running.");
            return R.ok("Container " + containerName + " is still running.");
        }
        else {
            return R.failure("Container " + containerName + " not found.");
        }
    }

    /**
     *
     * @author zrz
     * @date 2023/5/26
     * @time 17:29
     * @Description 删除指定镜像
     */
    @Override
    public R deleteContainer(String containerName){
        int result =  checkContainer(containerName);

        if (result == 2){
            DockerClient dockerClient = DockerClientBuilder.getInstance(host).build();
            RemoveContainerCmd removeContainerCmd = dockerClient.removeContainerCmd(containerName);
            removeContainerCmd.exec();
            System.out.println("Container " + containerName + " removed successfully.");
            return R.ok("Container " + containerName + " removed successfully.");
        } else if (result == 1) {
            System.out.println("Container " + containerName + " is still running.");
            return R.failure("Container " + containerName + " is still running.");
        }
            else {
            return R.failure("Container " + containerName + " not found.");
        }
    }

    @Autowired(required = false)
    private DataCleanTaskMapper dataCleanTaskMapper;

    @Override
    public int getPort(){
        ArrayList<Object> numbers = dataCleanTaskMapper.selectPortOrderByPort();
        for (int i = 8800; i <= 9000; i++) {
            if(!numbers.contains(i)){
                return i;
            }
        }
        return 0; // 两个个端口全部被占用的话，返回0
    }

    @Value("${host.ip}")
    public String ip;

    @Value("${host.username}")
    public String username;

    @Value("${host.password}")
    public String password;

    @Value("${host.port}")
    public Integer port;

    @Override
    public void mkdir(String folderPath){

        // 要创建的文件夹路径

        // 创建 JSch 对象
        JSch jsch = new JSch();

        try {
            // 连接远程 Linux 服务器
            Session session = jsch.getSession(username, ip, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            // 使用 SFTP 协议创建文件夹
            ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
            sftpChannel.connect();
            sftpChannel.mkdir(folderPath);
            sftpChannel.disconnect();
            session.disconnect();
            System.out.println("文件夹创建成功");
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }

    }



}
